from random import randint

from django.contrib.auth.hashers import make_password, check_password
from django.core.cache import cache
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from rest_framework_extensions.cache.mixins import CacheResponseMixin

from urlth.StaticMessages import successfullyMessage, errorMessage
from .Errors import UserPhoneRepeatCount, UserInfoNotFound, UserPasswordError
from .Permissions import UserInfoPermission
from .Serializers import *
from ..Base_app.Pagination import BasePagination


class UserViewSet(ModelViewSet, CacheResponseMixin):
    """角色信息管理"""
    queryset = UserModels.objects.all()
    serializer_class = UserSerializers_all.Srlist
    pagination_class = BasePagination
    authentication_classes = []
    filter_backends = [DjangoFilterBackend]
    filter_fields = {
        "user_name": ["icontains", "iexact"],
        "phone": ["icontains", "iexact"],
    }

    def get_serializer_class(self):
        # 根据请求类型动态变更serializer
        if self.action in ['create', "user_login", "set_password"]:
            return UserSerializers_all.UserCreate
        elif self.action == 'update':
            return UserSerializers_all.UserUpdate
        elif self.action == 'list':
            return UserSerializers_all.Srlist
        elif self.action in ["get_phone_code", "set_phone_code"]:
            return UserSerializers_all.UserPhoneCode
        elif self.action in ["user_info", "user_logout"]:
            return None
        return UserSerializers_all.UserReadOnly

    def create(self, request, *args, **kwargs):
        """
        - function: 用户注册api 接口实现
        - url: `/api/User/`
        - methods: `POST`
        - request: `{"pass_word": "string","phone": "string"}`
        - response:
            - 用户注册成功: `{"phone": "***********", "message": "user create successful", }` `static_code:201`
            - 用户手机号重复: `{"detail": "用户手机号以被注册"}` `static_code:403`
        """
        _serializer = self.get_serializer(data=request.data)
        _serializer.is_valid(raise_exception=True)
        if UserModels.UserPhoneHaves(UserPhone=_serializer.validated_data.get('phone')):
            raise UserPhoneRepeatCount
        else:
            pass_word = _serializer.validated_data.get("pass_word")
            _serializer.save(pass_word=make_password(pass_word))
            return Response(
                data={"phone": _serializer.validated_data.get('phone'), "message": successfullyMessage.PhoneCreated},
                status=status.HTTP_201_CREATED)

    @action(methods=['post'], detail=True, authentication_classes=[])
    def user_login(self, request, pk=None):
        """
        - function:用户登录功能 `用户登录成功后返回token值，当得到用户信息时通过token值进行操作`
        - url: `/api/User/user/user_login/`
        - method: `post`
        - request:`{"pass_word": "string","phone": "string"}` `并且在headers中添加 `AcceptAnces`
        - responses:
            - 登录成功 `{"phone": "***********", "token": "***-***-***-***-***","user_id": ******,"message": "user login successful"}` `status_code:200`
            - 用户密码错误 `{"detail": "用户密码错误,请重置密码或重新核对您的密码"}` `status_code:401`
            - 用户手机号没有找到  `{"detail": "用户手机号未注册，请前往注册"}` `status_code:404`
        """
        _serializer = self.get_serializer(data=request.data)
        _serializer.is_valid(raise_exception=True)
        _user_object = UserModels.UserPhoneHaves(UserPhone=_serializer.validated_data.get('phone'))
        if not _user_object:
            raise UserInfoNotFound
        elif not check_password(request.data.get('pass_word'), _user_object.pass_word):
            raise UserPasswordError
        else:
            _user_login_token = UserTokenModel.objects.update_or_create(user=_user_object,
                                                                        ipAddress=request.META['REMOTE_ADDR'],
                                                                        UserToken=UserTokenModel.create_user_token())
            return Response({"phone": _serializer.validated_data.get('phone'), "token": _user_login_token[0].UserToken,
                             "user_id": _user_login_token[0].user.id, "message": successfullyMessage.PhoneLoginSuccess},
                            status=status.HTTP_200_OK)

    @action(methods=['put'], detail=True)
    def set_password(self, request, pk=None):
        """
        - function: 用户重置密码
        - url: /api/User/user/set_password/
        - method: 'put'
        - request:``{"pass_word": "string","phone": "string"}``
        - responses:
            - 用户手机号没有找到  `{"detail": "用户手机号未注册，请前往注册"}` `status_code:404`
            - 用户重置密码成功 `{"phone": "******","message": "user set password successful"}` status_code:200``
        """
        _serializer = self.get_serializer(data=request.data)
        _serializer.is_valid(raise_exception=True)
        _user_object = UserModels.UserPhoneHaves(UserPhone=_serializer.validated_data.get("phone"))
        if not _user_object:
            raise UserInfoNotFound
        else:
            _user_object.__dict__.update(pass_word=make_password(_serializer.validated_data.get("pass_word")))
            _user_object.save()
            return Response(data={"phone": _serializer.validated_data.get("phone"),
                                  "message": successfullyMessage.PhoneSetPassword},
                            status=status.HTTP_200_OK)

    @action(methods=['post'], detail=True)
    def set_phone_code(self, request, pk=None):
        """
        - function: 得到用户手机验证码
        - url: `/api/User/user/set_phone_code/`
        - methods: `post`
        - request: `{"phone":"**********"}`
        - response: `{"phone":"***********", message:"*********"}` `status_code:200`
        """
        _serializer = self.get_serializer(data=request.data)
        _serializer.is_valid(raise_exception=True)
        code = randint(10000, 999999)
        cache.set(_serializer.validated_data.get("phone"), code, 60)
        print(cache.get(_serializer.validated_data.get("phone")))
        return Response(
            {"phone": _serializer.validated_data.get("phone"), "message": successfullyMessage.PhoneCodeSuccess},
            status=status.HTTP_200_OK)

    @action(methods=['post'], detail=True)
    def get_phone_code(self, request, pk=None):
        """
        - function: 验证用户手机验证码
        - url: `/api/User/user/get_phone_code/`
        - methods: `post`
        - request: `{"phone":"**********", "phoneCode": "*****"}`
        - response:
            - successful: `{"phone":"***********", message:""user set code successful"}` `status_code:200`
            - not successful: `{"phone":"***********", message:"user set code Not successful"}` `status_code:204`
        """
        _serializer = self.get_serializer(data=request.data)
        _serializer.is_valid(raise_exception=True)
        Set_Phone = str(cache.get(_serializer.data.get("phone"))) if cache.has_key(
            _serializer.validated_data.get("phone")) else str(None)
        _is_Bool = Set_Phone == _serializer.validated_data.get("phoneCode")
        return Response({"phone": _serializer.data.get("phone"), "message": successfullyMessage.PhoneCodeSuccess},
                        status=status.HTTP_200_OK) if _is_Bool else Response(
            {"phone": _serializer.data.get("phone"), "message": errorMessage.phoneCodeNotSuccessful},
            status=status.HTTP_204_NO_CONTENT)

    @action(methods=['get'], detail=True, permission_classes=[UserInfoPermission])
    def user_info(self, request, pk=None):
        """
        - function: 得到用户的个人信息 - url: `/api/User/user/user_info/?token={user_token(用户登录时拿到的token值)}` - methods: `get`
        - response: - token值为空，或token值不正确  {"detail": "请先前往进行登录"} - 得到用户信息成功 `{"id":******,"create_time":
        "2021-04-04T17:11:39.559482","update_time": "2021-04-04T17:38:28.496353","user_name": "未设置用户名","pass_word":
        "pbkdf2_sha256$216000$i48sTr40ufiP$KwOZAq4mkq4XSwt36mDBuvqnEUMFwv3DccNln9nWEMU=","phone": "15613115535",
        "avatar": null}`
        """
        _user_info = UserTokenModel.get_user_token(user_token=request.query_params.get("token", None))
        _serializer = UserSerializers_all.Srlist(_user_info.user, many=False)
        return Response(_serializer.data, status=status.HTTP_200_OK)

    @action(methods=['get'], detail=True, permission_classes=[UserInfoPermission])
    def user_logout(self, request, pk=None):
        """
        - function: 用户退出登录 - url: `/api/User/user/user_logout/?token={user_token(用户登录时拿到的token值)}` - methods: `get`
        - response: - token值为空，或token值不正确  {"detail": "请先前往进行登录"} - 得到用户信息成功 `{"phone": "15613115535",
        "message": "user logout successful"}`
        """
        _user_info = UserTokenModel.get_user_token(user_token=request.query_params.get("token", None))
        _user_info.UserToken = None
        _user_info.save()
        return Response({"phone": _user_info.user.phone, "message": successfullyMessage.PhoneLogoutSuccess},
                        status=status.HTTP_200_OK)
